#!usr/bin/python
# -*- coding: utf8 -*-
encoding='utf8'
'''утф'''

import os, sys, re, codecs
from Source import Source, Iter_plus
from Tokenize import Token, Tokenize
from Preprocess import Preprocess

## Start concatenation ##

class Expression(object):
    def __init__(self, parent = None):
        self.parent = parent
        self.type   = 'expression'
        self.src    = ''
        self.node_type = 'node'
        self.children  = Iter_plus()

    def parse(self, tokens):
        self.__parse(Iter_plus(tokens))

    def __parse(self, iter_plus):
        for t in iter_plus.byToken(True):
            if t.type == u'oper':
                if t.text() in u'{[(':
                    if len(self.children):
                        # Pass control to next level
                        new_exp = Expression()
                        new_exp.__parse(iter_plus)
                        self.children.append(new_exp)
                        self.children.move(1)
                    else:
                        self.children.append(t)
                        self.children.move(1)
                        if t.text() == u'{':
                            self.type = 'namespace'
                        elif t.text() == u'[':
                            self.type = 'array'
                    continue
                elif t.text() in u'}])':
                    # Pass control to previous level
                    self.children.append(t)
                    self.children.move(1)
                    return
                elif t.text() in u'"\'':
                    new_exp = Expression()
                    new_exp.__parse_string(iter_plus)
                    self.children.append(new_exp)
                    self.children.move(1)
                    continue
            self.children.append(t)
            self.children.move(1)

    def __parse_string(self, iter_plus):
        bslash = False
        t = iter_plus.read()
        self.children.append(t)
        stop_char = t.text()
        assert(stop_char in u'"\'')
        for t in iter_plus.byToken(True):
            self.children.append(t)
            self.children.move(1)
            if t.type == u'oper':
                if bslash:
                    bslash = False
                else:
                    if t.text() == u'\\':
                        bslash = True
                    elif t.text() == stop_char:
                        # Pass control to next level
                        self.type = 'string'
                        return

    def text(self):
        output = u''
        for t in self.children.byToken():
            output+= t.text()
        return output

class Compile(object):
    def __init__(self, tokens):
        self.tokens = tokens
        self.expression = Expression()
        self.groupExpressions()
        self.removeWhitespaces(self.expression)
        self.groupOperands()
        #print self.expression.text()
        return

    def expressions(self):
        return self.expression

    def removeWhitespaces(self, expression):
        for exp in expression.children.byToken():
            if exp.type == 'ws':
                expression.children.remove(True)
            elif exp.type == 'expression':
                self.removeWhitespaces( exp )

    def groupOperands(self):
        stack = [self.expression]
        duos = [
            [u'!=^&*+-<>|/%~', u'='],
            [u'-', u'>'],
            [u'/', u'/*'],
            [u'*', u'/'],
            [u'-', u'-'],
            [u'+', u'+'],
            [u'>', u'>'],
            [u'<', u'<'],
               ]
        trios = [
            [u'.', u'.', u'.']
                ]
        it_is_group = False
        while len(stack):
            exp = stack.pop()
            cs = exp.children
            for t in cs.byToken():
                if t.node_type == 'node':
                    stack.append(t)
                elif (cs.pos() >= 1) and (t.type == 'oper'):
                    for first, second in duos:
                         if t.src in second:
                            t_1 = cs.prev()
                            if t_1.type == 'oper':
                                if t_1.src in first:
                                    # Ok, it's group
                                    exp = Expression()
                                    exp.parse([t_1, t])
                                    cs.remove(True)
                                    cs.replace(exp)
                                    break
                    for first, second, third in trios:
                         if t.src in second:
                            t_1 = cs.prev()
                            t_3 = cs.next()
                            if t_1.type == 'oper' and t_3.type == 'oper':
                                if t_1.src in first and t_3.src in third:
                                    # Ok, it's group
                                    exp = Expression()
                                    exp.parse([t_1, t, t_3])
                                    cs.remove()
                                    cs.remove(True)
                                    cs.replace(exp)
                                    break

    def groupExpressions(self):
        self.expression.parse(self.tokens)

## Stop concatenation ##

def main():
    if 0:
        filename = 'tests/test_expression.cpp'
        s = Source(codecs.open(filename, 'r', 'utf8').read())
        t = Tokenize(s)
        t.Parse()
        e = Expression()
        e.parse(t.tokens)
        print e.text()
    elif 1:
        filename = 'tests\source3.cpp'
        s = Source(codecs.open(filename, 'r', 'utf8').read())
        p = Preprocess(s)
        p.preprocess()
        t = Tokenize(s)
        t.Parse()
        c = Compile(t.tokens)
        print c.expression.text()
        return
    elif 1:
        i = Iter_plus()
        print len(i)
        i.append(1)
        i.append(2)
        i.append(3)
        i.append(4)
        i.append(5)
        i1 = Iter_plus()
        print i1.get()
        flag = 0
        for t in i.byToken():
            print t
            if flag <= 2:
                i.append('!')
                i.move(1)
            flag+= 1
        print i.get()
        print len(i)

if __name__ == '__main__':
    main()
